#include "common.h"

#include "object.h"
#include "actor.h"
#include "actormanager.h"

#include "scene.h"
#include "scenemanager.h"

#include "tpvcamera.h"

IMPLEMENT_RTTI( TpvCamera, Camera )

TpvCamera::TpvCamera( const std::string& name )
:	Camera( name, false, false )
,	_distance( 0 )
,	_leftButtonPushed( false )
{
}

TpvCamera::~TpvCamera()
{
}

D3DXVECTOR3 TpvCamera::GetPosition()
{
	return GetSubjectiveTarget()->GetPosition();
}

D3DXMATRIX TpvCamera::GetProjectionMatirx()
{
	D3DXMATRIX mat;
	D3DXMatrixPerspectiveFovLH( &mat, D3DX_PI/4.0f, 1.0f, 1.0f, 1000.0f );

	return mat;
}

D3DXMATRIX TpvCamera::GetViewMatrix()
{
	D3DXVECTOR3 pos = this->GetPosition();
	D3DXVECTOR3 view = this->GetViewVector();

	D3DXMATRIX mat;
	D3DXMatrixLookAtLH( &mat, &pos, &( pos+view ), &D3DXVECTOR3( 0, 1.0f, 0 ) );

	return mat;
}

D3DXVECTOR3 TpvCamera::GetViewVector()
{
	D3DXVECTOR3 pos = GetSubjectiveTarget()->GetPosition();
	D3DXVECTOR3 look = GetObjectiveTarget()->GetPosition(); 
	D3DXVECTOR3 view = look - pos;

	D3DXVec3Normalize( &view, &view );

	return view;
}

void TpvCamera::OnLButtonPushed()
{
	_leftButtonPushed = true;
}

void TpvCamera::OnLButtonReleased()
{
	_leftButtonPushed = false;
}

void TpvCamera::OnMouseMoved( int dx, int dy )
{
	if( _leftButtonPushed )
	{
		// Rotation
		D3DXVECTOR3 up( 0, 1.0f, 0 );
		D3DXQUATERNION q;
		D3DXMATRIX mat;

		D3DXVECTOR3 view = GetViewVector();
		D3DXQuaternionRotationAxis( &q, &up, -0.01f*dx*1.0f/D3DX_PI );
		D3DXMatrixRotationQuaternion( &mat, &q );

		D3DXVECTOR4 temp;
		D3DXVec3Transform( &temp, &view, &mat );
		view = D3DXVECTOR3( temp.x, temp.y, temp.z );
		D3DXVec3Normalize( &view, &view );

		D3DXVECTOR3 right;
		D3DXVec3Cross( &right, &up, &view );
		D3DXQuaternionRotationAxis( &q, &right, -0.01f*dy*1.0f/D3DX_PI );
		D3DXMatrixRotationQuaternion( &mat, &q );

		D3DXVec3Transform( &temp, &view, &mat );
		view = D3DXVECTOR3( temp.x, temp.y, temp.z );
		D3DXVec3Normalize( &view, &view );

		D3DXVECTOR3 pos = GetObjectiveTarget()->GetPosition();
		GetSubjectiveTarget()->SetPosition( pos - ( view * _distance ) );
	}
}

void TpvCamera::OnRButtonPushed()
{
}

void TpvCamera::OnRButtonRelease()
{
}

void TpvCamera::OnWheelScrolled( int delta )
{
	float offset = ( delta > 0 )? 1.0f : -1.0f;

	D3DXVECTOR3 pos = this->GetPosition();
	D3DXVECTOR3 view = this->GetViewVector();
	this->SetPosition( pos+view*offset );
}

void TpvCamera::SetObjectiveTarget( Actor* target )
{
	Camera::SetObjectiveTarget( target );

	if( GetSubjectiveTarget() != NULL )
	{
		D3DXVECTOR3 p1 = GetSubjectiveTarget()->GetPosition();
		D3DXVECTOR3 p2 = target->GetPosition();

		_distance = D3DXVec3Length( &( p1 - p2 ) );
	}
}

void TpvCamera::SetPosition( const D3DXVECTOR3& pos )
{
	//GetSubjectiveTarget()->SetPosition( pos );
}

void TpvCamera::SetSubjectiveTarget( Actor* target )
{
	Camera::SetSubjectiveTarget( target );

	if( GetObjectiveTarget() != NULL )
	{
		D3DXVECTOR3 p1 = GetObjectiveTarget()->GetPosition();
		D3DXVECTOR3 p2 = target->GetPosition();

		_distance = D3DXVec3Length( &( p1 - p2 ) );
	}
}

void TpvCamera::SetViewVector( const D3DXVECTOR3& view )
{
}